<?php
define('AMUD_ERROR_MESSAGE','ERROR');
define('AMUD_DEBUG_MESSAGE','DEBUG');
define('AMUD_CHARACTER_MESSAGE','CHARACTER');
/**
 * MessageSystem class, hold and retrieve messages.
 * @static
 * @package meta
 * @author alcaitiff
 */
class MessageSystem
{
	private static  $messages=array();
    private static  $errorMessages=array();
    private static  $debugMessages=array();
    private static  $id=null;
                    /**
                     * @static
                     * @var boolean
                     * @access private
                     */
    private static  $debugOn=false;
	
	/**
     * Add a message to an user
     * @param string|ExportableObject $value Message
     * @param string $id Character name
     * @static
     * @return void
     */
	static public function addCharacterMessage($value,$id=null){
		if($value!=null){
			$id=self::verifyId($id);
			if($id==null){	
				array_push(self::$messages,$value);
			}else{
				self::saveMessage($id,$value,AMUD_CHARACTER_MESSAGE);
			}
		}
	}

	/**
     * Set the current user id
     * @param string $user
     * @static
     * @return void
     */
	static public function setUser($user){
		self::$id=$user;
	}
	
	/**
     * Set the current debug
     * @param boolean $value
     * @return void
     * @static
     */
	static public function setDebug($value){
		self::$debugOn=$value;
	}
	
	/**
     * Get the current debug
     * @return boolean
     * @static
     */
    static public function getDebug(){
		return self::$debugOn;
	}
	
	/**
     * Add a message to an array of characters
     * @param string|ExportableObject $message Message
     * @param array $chars Characters
     * @return void
     * @static
     */
	static public function broadcastMessage($message,$chars){
		if($message!=null)
			self::saveMessage($chars,$message,AMUD_CHARACTER_MESSAGE);
	}

	/**
     * Add an error message
     * @param string|ExportableObject $message Message
     * @return void
     * @static
     */
	static public function addErrorMessage($message){
		if(self::$id==null){	
			array_push(self::$errorMessages,$message);
		}else{
			self::saveMessage(self::$id,$message,AMUD_ERROR_MESSAGE);
		}
	}
	
	/**
     * Add a debug message
     * @static
     * @param string|ExportableObject $message Message
     * @return void
     */
	static public function addDebugMessage($message){
		if(self::$debugOn){
			if(self::$id==null){	
				array_push(self::$debugMessages,$message);
			}else{
				self::saveMessage(self::$id,$message,AMUD_DEBUG_MESSAGE);
			}
		}
	}	
	
	/**
     * @static
     * @param string $id ID
     * @return string 
     */
    static private function verifyId($id){
		if($id==null){
			return self::$id;
		}else{
			return $id;
		}
	}
	
	/**
     * Get messages for an user
     * @param int $num Number of messages
     * @return array
     * @static
     */
	static public function getCharacterMessages($num){
		$ret=array_values(self::$messages);
		$ret=array_merge($ret,self::getMessages(self::$id,AMUD_CHARACTER_MESSAGE,$num));
		return $ret;
	}
    /**
     * Get error messages
     * @param int $num Number of messages
     * @return array
     * @static
     */
	static public function getErrorMessages($num){
		$ret=array_values(self::$errorMessages);
		$ret=array_merge($ret,self::getMessages(self::$id,AMUD_ERROR_MESSAGE,$num));
		return $ret;
	}
    /**
     * Get debug messages
     * @param int $num Number of messages
     * @return array
     * @static
     */
	static public function getDebugMessages($num){
		$ret=array_values(self::$debugMessages);
		$ret=array_merge($ret,self::getMessages(self::$id,AMUD_DEBUG_MESSAGE,$num));
		return $ret;
	}
    //***********************************************************************************************************
    //					DATABASE METHODS
    //***********************************************************************************************************
	
	/**
     * Save a message
     * @param array $ids Characters names
     * @param string|ExportableObject $value Message
     * @param string $type Type of message
     * @return void
     * @static
     */
    static private function saveMessage($ids,$value,$type){
		$dbo=new DB();
		$db=$dbo->db;
		$stmt = $db->prepare(	'INSERT INTO messages '.
								'(char_id,content,type,micro_time) '.
								'VALUES '.
								'(?,?,?,?)'
									);
		$time=microtime(true);
		if(!is_array($ids)){
			$stmt->bind_param('sssd',$ids,base64_encode(serialize($value)),$type,$time);									
		    $stmt->execute();
		}else{
			foreach($ids as $id){
				$stmt->bind_param('sssd',$id,base64_encode(serialize($value)),$type,$time);									
			    $stmt->execute();
			}
		}
	    $stmt->close();
	}

	//here I can make a better function if I store the results and fetch in each call
	//but this will be done later and only if is really needed
    /**
     * Get the character messages
     * @param string $id string
     * @param string $type Type of message
     * @param int $limit Max of messages
     * @return string|ExportableObject
     * @static
     */
	static private function getMessages($id,$type,$limit=1){
		$ret=array();
		$content=null;
		$ts=0;
		$dbo=new DB();
		$db=$dbo->db;
		$select = $db->prepare(	'SELECT content,micro_time '.
								'FROM messages '.
								'WHERE (char_id=? and type=?) '.
								'ORDER BY micro_time ASC '.
								'LIMIT ?'
									);
		$select->bind_param('ssi',$id,$type,$limit);									
		$select->bind_result($content,$time);
	    $select->execute();
	    while($select->fetch()){
	    	$ret[]=unserialize(base64_decode($content));
	    }
       	$select->close();
       	self::removeMessages($id,$type,$time);
	    return $ret;
	}
    /**
     * Remove messages
     * @param string $id Character name
     * @param string $type Message type
     * @param int $time Timestamp
     * @return void
     * @static
     */
	static private function removeMessages($id,$type,$time){
		$dbo=new DB();
		$db=$dbo->db;
    	$delete = $db->prepare(	'DELETE '.
								'FROM messages '.
								'WHERE (char_id=? and type=? and micro_time<=?) '
								);
		$delete->bind_param('ssd',$id,$type,$time);									
	    $delete->execute();
	    $delete->close();
	}
}